home *** CD-ROM | disk | FTP | other *** search
- #define NAME "Join"
- #define REVISION "20"
- #define DATE "13.07.2001"
-
- /* Programmheader
-
- Name: Join
- Author: SDI
- Distribution: PD
- Description: joins files to one big file
- Compileropts: -
- Linkeropts: -gsi
-
- 1.4 03.10.95 : JoinToH and JoinToAG included
- 1.5 04.10.95 : AS as synonym for TO
- 1.6 15.10.95 : recompiled
- 1.7 15.02.95 : parameters now like in C:Join! AS=TO/K/A, FILE/M/A and
- new parameter FILELIST --> Same function like before needs now AS
- or TO and FILELIST!, used own startup code, new option NAMEHEADER
- 1.8 16.02.96 : option NAMEHEADER now also processes very long file names,
- removed some other bugs
- 1.9 17.04.96 : added options ADD and DELSOURCE
- 1.10 27.04.96 : fixed error with name-printout, added option QUIET
- 1.11 04.05.96 : fixed error with ReadArgs
- 1.12 28.05.96 : now uses SDI_defines SDI_ENDCODE
- 1.13 12.02.97 : added option SPLITTED
- 1.14 18.03.97 : SDI include names changed
- 1.15 01.05.97 : added pattern matching, ALL and PATTERN options, made
- multi-reentrant (pure bit) and removed SDI funcs this way
- 1.16 03.05.97 : added workbench tooltype call
- 1.17 04.05.97 : fixed a little bug
- 1.18 07.06.97 : fixed problem, when source == destination
- 1.19 21.08.99 : fixed PATTERN Problem
- 1.20 13.07.01 : fixed empty file problem
- */
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/icon.h>
- #include <workbench/startup.h>
- #include <exec/memory.h>
- #include "SDI_version.h"
- #define SDI_TO_ANSI
- #include "SDI_ASM_STD_protos.h"
-
- #define PARAM "FILE/M,AS=TO/K/A,FILELIST/K,SPLITTED/K,PAT=PATTERN/K," \
- "OUTPUT/K,AG=AMIGAGUIDE/S,HEADER/S,NAMEHEADER/S,ADD/S," \
- "DEL=DELSOURCE/S,QUIET/S,ALL/S,NOPAT=NOPATTERN/S"
- #define PATHNAME_SIZE 256
- #define NAMEHEADER_SIZE 69
- #define HEADERLINE_SIZE 78
-
- #define JOINFLAG_AMIGAGUIDE (1<<0)
- #define JOINFLAG_HEADER (1<<1)
- #define JOINFLAG_NAMEHEADER (1<<2)
- #define JOINFLAG_DELSOURCE (1<<3)
- #define JOINFLAG_QUIET (1<<4)
- #define JOINFLAG_NOPATTERN (1<<5)
- #define JOINFLAG_ALL (1<<6)
-
- #define JOINERR_NOMEM 1
- #define JOINERR_NOFILE 2
- #define JOINERR_READERR 3
- #define JOINERR_WRITEERR 4
- #define JOINERR_BREAK 5
-
- struct ExecBase *SysBase;
- struct DosLibrary *DOSBase;
- struct Library *IconBase;
- static const STRPTR line =
- "\n/* ===================================================================== */\n\n";
-
- struct Args
- {
- STRPTR*files;
- STRPTR to;
- STRPTR filelist;
- STRPTR splitted;
- STRPTR pattern;
- STRPTR output;
- LONG amigaguide;
- LONG header;
- LONG nameheader;
- LONG add;
- LONG delsource;
- LONG quiet;
- LONG all;
- LONG nopattern;
- };
-
- static ULONG JoinMain(struct CSource *CSource);
- static ULONG Join(STRPTR name, ULONG filehandle, ULONG Flags);
- static ULONG PatJoin(STRPTR name, ULONG filehandle, ULONG Flags, STRPTR pat);
- static ULONG GetLength(ULONG fh);
-
- ULONG start(void)
- {
- struct Process *task;
- struct WBStartup *msg = 0;
- ULONG ret = RETURN_FAIL;
- struct DosLibrary *dosbase;
- struct CSource csr;
-
- SysBase = (*((struct ExecBase **) 4));
- /* test for WB and reply startup-message */
- if(!(task = (struct Process *) FindTask(0))->pr_CLI)
- {
- WaitPort(&task->pr_MsgPort);
- msg = (struct WBStartup *) GetMsg(&task->pr_MsgPort);
- }
-
- memset(&csr, 0, sizeof(struct CSource));
- if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
- {
- DOSBase = dosbase;
-
- if(!msg) /* CLI call - only one argument string */
- ret = JoinMain(&csr);
- else
- {
- struct Library *iconbase;
-
- if((iconbase = OpenLibrary("icon.library", 37)))
- {
- ULONG i;
- IconBase = iconbase;
-
- ret = RETURN_OK;
- for(i = 0; !ret && i < msg->sm_NumArgs; ++i)
- {
- ULONG lock;
- struct DiskObject *dobj;
-
- lock = CurrentDir(msg->sm_ArgList[i].wa_Lock);
- if((dobj = GetDiskObject(msg->sm_ArgList[i].wa_Name)))
- {
- if(dobj->do_ToolTypes)
- {
- char **str = dobj->do_ToolTypes;
-
- while(!ret && *str)
- {
- STRPTR buf;
- csr.CS_Length = strlen(*str)+1; /* add \n */
- if((buf = (STRPTR) AllocMem(csr.CS_Length+1, MEMF_ANY)))
- {
- CopyMem(*str, buf, csr.CS_Length);
- buf[csr.CS_Length] = 0;
- buf[csr.CS_Length-1] = '\n';
- csr.CS_Buffer = buf;
- ret = JoinMain(&csr);
- FreeMem(buf, csr.CS_Length+1);
- }
- else
- ret = RETURN_FAIL;
- ++str;
- }
- }
- FreeDiskObject(dobj);
- }
- CurrentDir(lock);
- }
- CloseLibrary(iconbase);
- }
- }
- CloseLibrary((struct Library *) dosbase);
- }
-
- if(msg)
- {
- Forbid();
- ReplyMsg((struct Message *) msg);
- }
-
- return ret;
- }
-
- static ULONG JoinMain(struct CSource *CSource)
- {
- struct Args args;
- LONG i = 0;
- ULONG Flags = 0, ret = RETURN_FAIL, dest, patbufsize = 0, out = 0, oldout = 0;
- STRPTR pattern = 0;
- struct RDArgs *rda;
-
- memset(&args, 0, sizeof(struct Args));
- if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
- {
- rda->RDA_ExtHelp =
- "FILES files, which should be joined\n"
- "FILELIST takes the filenames out of a file (every line contains\n"
- " a complete filename)\n"
- "SPLITTED allows joining splitted files, data has to look like:\n"
- " <filename>[,<first number>[,<last number>]], filename has\n"
- " to hold ONE format string like %ld,%03ld,%lx,%2lx,\n"
- " numbers have to be decimal\n\n"
- "PATTERN gives pattern filename must match\n"
- "OUTPUT specifies output path\n\n"
- "AMIGAGUIDE at the start of every file @node \"filename\" and at the\n"
- " end @endnode is inserted\n"
- "HEADER /* ======== ... ========= */ is inserted at filestart\n"
- "NAMEHEADER /* ===... filename ...=== */ is inserted at filestart\n"
- "ADD adds the files to an existing destination file\n"
- "DELSOURCE deletes the sourcefiles\n"
- "QUIET brings no output\n"
- "ALL scan into directories\n"
- "NOPATTERN take names as given";
-
- rda->RDA_Source.CS_Buffer = CSource->CS_Buffer;
- rda->RDA_Source.CS_Length = CSource->CS_Length;
-
- if(ReadArgs(PARAM, (LONG *) &args, rda))
- {
- if(args.amigaguide) Flags |= JOINFLAG_AMIGAGUIDE;
- if(args.header) Flags |= JOINFLAG_HEADER;
- if(args.nameheader) Flags |= JOINFLAG_NAMEHEADER;
- if(args.delsource) Flags |= JOINFLAG_DELSOURCE;
- if(args.quiet) Flags |= JOINFLAG_QUIET;
- if(args.nopattern) Flags |= JOINFLAG_NOPATTERN;
- if(args.all) Flags |= JOINFLAG_ALL;
-
- if(args.output && (out = Open(args.output, MODE_NEWFILE)))
- oldout = SelectOutput(out);
-
- if(args.files) ++i;
- if(args.filelist) ++i; /* test if only one of these three */
- if(args.splitted) ++i;
- if(i == 1 && (dest = Open(args.to, MODE_READWRITE)))
- {
- if(args.add)
- Seek(dest, 0, OFFSET_END);
- else
- SetFileSize(dest, 0, OFFSET_BEGINNING); /* cut when already exists */
-
- if(args.pattern && *args.pattern)
- {
- patbufsize = (strlen(args.pattern)<<1) + 1;
- if((pattern = (STRPTR) AllocMem(patbufsize, MEMF_PUBLIC)))
- {
- if(ParsePatternNoCase(args.pattern, pattern, patbufsize) < 0)
- {
- FreeMem(pattern, patbufsize); pattern = 0;
- }
- }
- }
-
- if(args.pattern && !pattern)
- {
- if(!*args.pattern)
- SetIoErr(ERROR_BAD_TEMPLATE);
- }
- else if(args.splitted)
- {
- UBYTE name[PATHNAME_SIZE];
- STRPTR a, b, *e = 0, *f = 0;
- LONG spl_start = 0, spl_end = 0;
-
- ret = RETURN_OK;
- for(a = args.splitted; *a && *a != ','; ++a)
- ;
- if(*a == ',')
- {
- *(a++) = 0;
- for(b = a; *b && *b != ','; ++b)
- ;
-
- if(*b == ',')
- {
- *(b++) = 0;
- spl_end = strtol(b,f,10);
- }
- spl_start = strtol(a,e,10);
-
- if(e || f || (spl_end && spl_end < spl_start))
- {
- SetIoErr(ERROR_BAD_NUMBER);
- ret = RETURN_FAIL;
- }
- }
-
- while(!ret && (!spl_end || spl_end >= spl_start))
- {
- sprintf(name, args.splitted, spl_start++);
- if((i = PatJoin(name, dest, Flags, pattern)))
- {
- if(i != JOINERR_NOFILE)
- ret = RETURN_FAIL;
- else if(!spl_end)
- break;
- }
- }
- }
- else if(args.filelist)
- {
- ULONG fh, bufsize;
- STRPTR buffer, pos, name;
-
- if((fh = Open(args.filelist, MODE_OLDFILE)))
- {
- bufsize = GetLength(fh);
- if((pos = buffer = (STRPTR) AllocMem(bufsize+1, MEMF_ANY)))
- {
- if(Read(fh, buffer, bufsize) == bufsize)
- {
- ret = RETURN_OK;
- while(pos < buffer + bufsize)
- {
- name = pos;
- while(pos < buffer + bufsize && *pos != '\n')
- ++pos;
- *(pos++) = 0;
- if(PatJoin(name, dest, Flags, pattern))
- ret = RETURN_FAIL;
- }
- }
- FreeMem(buffer, bufsize+1);
- }
- Close(fh);
- }
- }
- else
- {
- ret = RETURN_OK;
- while(*args.files)
- {
- if(PatJoin(*(args.files++), dest, Flags, pattern))
- {
- ret = RETURN_FAIL; break;
- }
- }
- }
- if(pattern)
- FreeMem(pattern, patbufsize);
- Close(dest);
- } /* Open dest */
- else if(!i)
- SetIoErr(ERROR_REQUIRED_ARG_MISSING);
- else if(i != 1)
- SetIoErr(ERROR_TOO_MANY_ARGS);
-
- FreeArgs(rda);
- } /* ReadArgs */
- FreeDosObject(DOS_RDARGS, rda);
- }
-
- if(!ret && (SetSignal(0L,0L) & SIGBREAKF_CTRL_C))
- {
- SetIoErr(ERROR_BREAK);
- ret = RETURN_WARN;
- }
-
- if(ret && !args.quiet)
- PrintFault(IoErr(),0);
-
- if(out)
- Close(SelectOutput(oldout));
-
- return ret;
- }
-
- /* every list entry of filelist is a memory block which contains pointer
- to next block and behind this the filename string */
-
- static ULONG PatJoin(STRPTR name, ULONG dest, ULONG Flags, STRPTR pattern)
- {
- if(Flags & JOINFLAG_NOPATTERN)
- return Join(name, dest, Flags);
- else
- {
- struct AnchorPath *APath;
- ULONG *filelist = 0, *a, *b, retval;
- ULONG ret = JOINERR_NOMEM;
- LONG i;
-
- if((APath = (struct AnchorPath *) AllocMem(sizeof(struct AnchorPath)+
- PATHNAME_SIZE, MEMF_PUBLIC|MEMF_CLEAR)))
- {
- APath->ap_BreakBits = SIGBREAKF_CTRL_C;
- APath->ap_Strlen = PATHNAME_SIZE;
-
- for(retval = MatchFirst(name, APath); !retval; retval =MatchNext(APath))
- {
- if(APath->ap_Flags & APF_DIDDIR)
- APath->ap_Flags &= ~APF_DIDDIR;
- else if(APath->ap_Info.fib_DirEntryType > 0)
- {
- if(Flags & JOINFLAG_ALL)
- APath->ap_Flags |= APF_DODIR;
- }
- else if(!pattern || MatchPatternNoCase(pattern, APath->ap_Buf))
- {
- i = strlen(APath->ap_Buf)+1;
- if(!(a = (ULONG *) AllocVec(i+4, MEMF_ANY)))
- break;
- CopyMem(APath->ap_Buf, a+1, i);
- if(!filelist)
- {
- filelist = a; *a = 0;
- }
- else if(stricmp((STRPTR) (filelist+1), APath->ap_Buf) >= 0)
- {
- *a = (ULONG) filelist; filelist = a;
- }
- else
- {
- for(b = filelist; *b && (i = stricmp((STRPTR) (*b+4),
- APath->ap_Buf)) < 0; b = (ULONG *) *b)
- ;
- *a = *b; *b = (ULONG) a;
- }
- }
- }
- MatchEnd(APath);
-
- if(retval == ERROR_NO_MORE_ENTRIES)
- {
- for(a = filelist; a; a = (ULONG *) *a)
- {
- if((ret = Join((STRPTR) (a+1), dest, Flags)))
- break;
- }
- }
-
- while(filelist)
- {
- a = (ULONG *) *filelist;
- FreeVec(filelist);
- filelist = a;
- }
- FreeMem(APath, sizeof(struct AnchorPath)+PATHNAME_SIZE);
- }
- return ret;
- }
- }
-
- static ULONG Join(STRPTR name, ULONG dest, ULONG Flags)
- {
- ULONG file, lock_old, lock_new, bufsize, ret = 0;
- LONG i;
- UBYTE namebuffer[NAMEHEADER_SIZE+1];
- ULONG namel;
- STRPTR buffer;
-
- if((lock_new = Lock(name, SHARED_LOCK)))
- {
- if((lock_old = DupLockFromFH(dest)))
- {
- if(SameLock(lock_new, lock_old) == LOCK_SAME)
- {
- if(!(Flags & JOINFLAG_QUIET))
- PutStr("Destination file skipped.\n");
- UnLock(lock_new); lock_new = 0;
- }
- UnLock(lock_old);
- }
- }
- else
- ret = JOINERR_NOFILE;
-
- if(!lock_new)
- return ret;
-
- if((file = OpenFromLock(lock_new)))
- {
- bufsize = GetLength(file);
- if((i = AvailMem(MEMF_LARGEST)) < bufsize)
- bufsize = i;
- if(!bufsize)
- bufsize = 1; /* prevent allocmem failure */
- if((buffer = (STRPTR) AllocMem(bufsize, MEMF_ANY)))
- {
- if(Flags & JOINFLAG_AMIGAGUIDE)
- {
- Write(dest, "@node \"", 7);
- Write(dest, name, i);
- Write(dest, "\"\n", 2);
- }
- if(Flags & JOINFLAG_HEADER && Seek(dest, 0, OFFSET_CURRENT))
- Write(dest, line, HEADERLINE_SIZE);
- namel = strlen(name);
- if(namel > NAMEHEADER_SIZE)
- {
- namebuffer[0] = namebuffer[1] = namebuffer[2] = '.';
- CopyMem(name+namel-(NAMEHEADER_SIZE-3), namebuffer+3, NAMEHEADER_SIZE-3+1);
- namel = NAMEHEADER_SIZE;
- }
- else
- CopyMem(name, namebuffer, namel+1);
- if(Flags & JOINFLAG_NAMEHEADER)
- {
- i = (NAMEHEADER_SIZE-namel)>>1;
- Write(dest, line, 3+i);
- Write(dest, " ", 1);
- Write(dest, namebuffer, namel);
- Write(dest, " ", 1);
- i += 5+namel;
- Write(dest, line+i, HEADERLINE_SIZE-i);
- }
- while((i = Read(file, buffer, bufsize)) > 0)
- {
- if(Write(dest, buffer, i) == -1)
- {
- ret = JOINERR_WRITEERR; break;
- }
- }
- if(i == -1)
- ret = JOINERR_READERR;
-
- if(!ret && (Flags & JOINFLAG_AMIGAGUIDE))
- Write(dest, "\n@endnode\n\n", 11);
-
- FreeMem(buffer, bufsize);
- }
- else
- ret = JOINERR_NOMEM;
- Close(file);
- }
- else
- {
- UnLock(lock_new);
- ret = JOINERR_NOFILE;
- }
-
- if(!ret)
- {
- if(Flags & JOINFLAG_DELSOURCE)
- DeleteFile(name);
- if(!(Flags & JOINFLAG_QUIET))
- {
- PutStr(namebuffer); PutStr(" joined");
- if(Flags & JOINFLAG_DELSOURCE)
- PutStr(" and deleted");
- PutStr(".\n");
- }
- if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
- ret = JOINERR_BREAK;
- }
- return ret;
- }
-
- static ULONG GetLength(ULONG fh)
- {
- struct FileInfoBlock *fib;
- ULONG ret = 0xFFFFFFFF;
-
- if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
- {
- if(ExamineFH(fh, fib))
- ret = fib->fib_Size;
- FreeDosObject(DOS_FIB,fib);
- }
- return ret;
- }
-